/**
 * 
 */
package com.wubo.sec.core;

import java.util.Collection;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;

/**
 * @author wubo
 * @version V1.0.01
 */
public class UserLoginPageHelper {
	private final static Log logger = LogFactory.getLog(UserLoginPageHelper.class);
	public final static String SCRIPT_REQUIRED_LOGIN_JSON_RESULT = "_script_login_json_result";
	public final static String SCRIPT_LOGIN_ERROR = "_script_login_error";
	
	private final static ThreadLocal<String> loginPageHolder = new ThreadLocal<String>();
	private final static ThreadLocal<String> markHolder = new ThreadLocal<String>();

	public final static String DEFAULT_LOGIN_PAGE = "/login.jsp";
	
	public final static String COOKIE_NAME = "_user_login_page";
	
	public final static int COOKIE_MAX_AGE = 60 * 60 * 24 * 90; //三个月
	
	private static Map<String, UserLoginProcessor> loginProcessors;
	
	static void setLoginProcessor(Map<String, UserLoginProcessor> loginProcessors){
		UserLoginPageHelper.loginProcessors = loginProcessors;
	}
	
	static void setLoginPage(String loginPage){
		logger.debug("Set login page " + loginPage + " to LoginPageHolder .");
		loginPageHolder.set(loginPage);
	}
	
	static void setMark(String mark){
		markHolder.set(mark);
	}
	
	static void clearMark(){
		markHolder.remove();
	}
	
	public static String getLoginPageUrl(HttpServletRequest request){
		return getLoginPage(request);
	}
	
	static String getLoginFailureUrl(HttpServletRequest request){
		String loginPage = getLoginPage(request);
		
		String concat = "?";
		
		if(loginPage.indexOf("?") != -1){
			concat = "&";
		}
		return loginPage+concat+getErrorParameter();
	}
	
	static UserLoginProcessor getLoginProcessor(){
		String mark = markHolder.get();
		if(mark != null){
			return loginProcessors.get(mark);
		}
		logger.info("There is no mark had be found .");
		
		UserLoginProcessor loginProcessor = loginProcessors.get("");
		if(loginProcessor != null){
			return loginProcessor;
		}
		return loginProcessors.values().iterator().next();
	}
	
	static Collection<UserLoginProcessor> getLoginProcessors(){
		return loginProcessors.values();
	}
	
	private static String getLoginPage(HttpServletRequest request){
		String loginPage = loginPageHolder.get();
		
		if(loginPage == null){
			loginPage = retrieveLoginPageFromCookie(request);
			logger.debug("Retrieve login page from cookie : "+loginPage);
		}
		if(loginPage == null){
			loginPage = DEFAULT_LOGIN_PAGE;
			logger.debug("Get default login page to login : "+loginPage);
		}
		logger.debug("Login page is "+loginPage);
		return loginPage;
	}
	
	private static String getErrorParameter(){
		return "login_error=1";
	}
	
	private static String retrieveLoginPageFromCookie(HttpServletRequest request){
		Cookie[] cookies = request.getCookies();
		if ((cookies == null) || (cookies.length == 0)) {
            return null;
        }

        for (int i = 0; i < cookies.length; i++) {
            if (COOKIE_NAME.equals(cookies[i].getName())) {
                return cookies[i].getValue();
            }
        }

        return null;
	}
	
	static void setLoginPageCookie(String cookieValue, HttpServletRequest request, HttpServletResponse response){
		String loginPageCookie = retrieveLoginPageFromCookie(request);
		if(loginPageCookie == null || ! loginPageCookie.equals(cookieValue)){
			Cookie cookie = new Cookie(COOKIE_NAME, cookieValue);
	        cookie.setMaxAge(COOKIE_MAX_AGE);
	        cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/");
	        logger.debug("Add login page " + cookieValue + " to Cookie " + COOKIE_NAME+", Path is " + cookie.getPath());
	        response.addCookie(cookie);
		}
	}
	
	public static boolean isScriptRequest(HttpServletRequest request){
		 String xRequestedWith = request.getHeader("X-Requested-With");
		 if(StringUtils.hasText(xRequestedWith)){
			 return "XMLHttpRequest".equals(xRequestedWith);
		 }
		 String requestType = request.getHeader("RequestType");
		 if(StringUtils.hasText(requestType)){
			 return "request-in-script".equals(requestType);
		 }
		 return false;
	}
}
